home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / perl5 / PPI / Dumper.pm < prev    next >
Encoding:
Perl POD Document  |  2010-07-06  |  6.7 KB  |  311 lines

  1. package PPI::Dumper;
  2.  
  3. =pod
  4.  
  5. =head1 NAME
  6.  
  7. PPI::Dumper - Dumping of PDOM trees
  8.  
  9. =head1 SYNOPSIS
  10.  
  11.   # Load a document
  12.   my $Module = PPI::Document->new( 'MyModule.pm' );
  13.   
  14.   # Create the dumper
  15.   my $Dumper = PPI::Dumper->new( $Module );
  16.   
  17.   # Dump the document
  18.   $Dumper->print;
  19.  
  20. =head1 DESCRIPTION
  21.  
  22. The PDOM trees in PPI are quite complex, and getting a dump of their
  23. structure for development and debugging purposes is important.
  24.  
  25. This module provides that functionality.
  26.  
  27. The process is relatively simple. Create a dumper object with a
  28. particular set of options, and then call one of the dump methods to
  29. generate the dump content itself.
  30.  
  31. =head1 METHODS
  32.  
  33. =cut
  34.  
  35. use strict;
  36. use Params::Util qw{_INSTANCE};
  37.  
  38. use vars qw{$VERSION};
  39. BEGIN {
  40.     $VERSION = '1.213';
  41. }
  42.  
  43.  
  44.  
  45.  
  46.  
  47. #####################################################################
  48. # Constructor
  49.  
  50. =pod
  51.  
  52. =head2 new $Element, param => value, ...
  53.  
  54. The C<new> constructor creates a dumper, and takes as argument a single
  55. L<PPI::Element> object of any type to serve as the root of the tree to
  56. be dumped, and a number of key-E<gt>value parameters to control the output
  57. format of the Dumper. Details of the parameters are listed below.
  58.  
  59. Returns a new C<PPI::Dumper> object, or C<undef> if the constructor
  60. is not passed a correct L<PPI::Element> root object.
  61.  
  62. =over
  63.  
  64. =item memaddr
  65.  
  66. Should the dumper print the memory addresses of each PDOM element.
  67. True/false value, off by default.
  68.  
  69. =item indent
  70.  
  71. Should the structures being dumped be indented. This value is numeric,
  72. with the number representing the number of spaces to use when indenting
  73. the dumper output. Set to '2' by default.
  74.  
  75. =item class
  76.  
  77. Should the dumper print the full class for each element.
  78. True/false value, on by default.
  79.  
  80. =item content
  81.  
  82. Should the dumper show the content of each element. True/false value,
  83. on by default.
  84.  
  85. =item whitespace
  86.  
  87. Should the dumper show whitespace tokens. By not showing the copious
  88. numbers of whitespace tokens the structure of the code can often be
  89. made much clearer. True/false value, on by default.
  90.  
  91. =item comments
  92.  
  93. Should the dumper show comment tokens. In situations where you have
  94. a lot of comments, the code can often be made clearer by ignoring
  95. comment tokens. True/value value, on by default.
  96.  
  97. =item locations
  98.  
  99. Should the dumper show the location of each token. The values shown are
  100. [ line, rowchar, column ]. See L<PPI::Element/"location"> for a description of
  101. what these values really are. True/false value, off by default.
  102.  
  103. =back
  104.  
  105. =cut
  106.  
  107. sub new {
  108.     my $class   = shift;
  109.     my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
  110.  
  111.     # Create the object
  112.     my $self = bless {
  113.         root    => $Element,
  114.         display => {
  115.             memaddr    => '', # Show the refaddr of the item
  116.             indent     => 2,  # Indent the structures
  117.             class      => 1,  # Show the object class
  118.             content    => 1,  # Show the object contents
  119.             whitespace => 1,  # Show whitespace tokens
  120.             comments   => 1,  # Show comment tokens
  121.             locations  => 0,  # Show token locations
  122.             },
  123.         }, $class;
  124.  
  125.     # Handle the options
  126.     my %options = map { lc $_ } @_;
  127.     foreach ( keys %{$self->{display}} ) {
  128.         if ( exists $options{$_} ) {
  129.             if ( $_ eq 'indent' ) {
  130.                 $self->{display}->{indent} = $options{$_};
  131.             } else {
  132.                 $self->{display}->{$_} = !! $options{$_};
  133.             }
  134.         }
  135.     }
  136.  
  137.     $self->{indent_string} = join '', (' ' x $self->{display}->{indent});
  138.  
  139.     $self;
  140. }
  141.  
  142.  
  143.  
  144.  
  145.  
  146. #####################################################################
  147. # Main Interface Methods
  148.  
  149. =pod
  150.  
  151. =head2 print
  152.  
  153. The C<print> method generates the dump and prints it to STDOUT.
  154.  
  155. Returns as for the internal print function.
  156.  
  157. =cut
  158.  
  159. sub print {
  160.     CORE::print(shift->string);
  161. }
  162.  
  163. =pod
  164.  
  165. =head2 string
  166.  
  167. The C<string> method generates the dump and provides it as a
  168. single string.
  169.  
  170. Returns a string or undef if there is an error while generating the dump. 
  171.  
  172. =cut
  173.  
  174. sub string {
  175.     my $array_ref = shift->_dump or return undef;
  176.     join '', map { "$_\n" } @$array_ref;
  177. }
  178.  
  179. =pod
  180.  
  181. =head2 list
  182.  
  183. The C<list> method generates the dump and provides it as a raw
  184. list, without trailing newlines.
  185.  
  186. Returns a list or the null list if there is an error while generation
  187. the dump.
  188.  
  189. =cut
  190.  
  191. sub list {
  192.     my $array_ref = shift->_dump or return ();
  193.     @$array_ref;
  194. }
  195.  
  196.  
  197.  
  198.  
  199.  
  200. #####################################################################
  201. # Generation Support Methods
  202.  
  203. sub _dump {
  204.     my $self    = ref $_[0] ? shift : shift->new(shift);
  205.     my $Element = _INSTANCE($_[0], 'PPI::Element') ? shift : $self->{root};
  206.     my $indent  = shift || '';
  207.     my $output  = shift || [];
  208.  
  209.     # Print the element if needed
  210.     my $show = 1;
  211.     if ( $Element->isa('PPI::Token::Whitespace') ) {
  212.         $show = 0 unless $self->{display}->{whitespace};
  213.     } elsif ( $Element->isa('PPI::Token::Comment') ) {
  214.         $show = 0 unless $self->{display}->{comments};
  215.     }
  216.     push @$output, $self->_element_string( $Element, $indent ) if $show;
  217.  
  218.     # Recurse into our children
  219.     if ( $Element->isa('PPI::Node') ) {
  220.         my $child_indent = $indent . $self->{indent_string};
  221.         foreach my $child ( @{$Element->{children}} ) {
  222.             $self->_dump( $child, $child_indent, $output );
  223.         }
  224.     }
  225.  
  226.     $output;
  227. }
  228.  
  229. sub _element_string {
  230.     my $self    = ref $_[0] ? shift : shift->new(shift);
  231.     my $Element = _INSTANCE($_[0], 'PPI::Element') ? shift : $self->{root};
  232.     my $indent  = shift || '';
  233.     my $string  = '';
  234.  
  235.     # Add the memory location
  236.     if ( $self->{display}->{memaddr} ) {
  237.         $string .= $Element->refaddr . '  ';
  238.     }
  239.         
  240.         # Add the location if such exists
  241.     if ( $self->{display}->{locations} ) {
  242.         my $loc_string;
  243.         if ( $Element->isa('PPI::Token') ) {
  244.             my $location = $Element->location;
  245.             if ($location) {
  246.                 $loc_string = sprintf("[ % 4d, % 3d, % 3d ] ", @$location);
  247.             }
  248.         }
  249.         # Output location or pad with 20 spaces
  250.         $string .= $loc_string || " " x 20;
  251.     }
  252.         
  253.     # Add the indent
  254.     if ( $self->{display}->{indent} ) {
  255.         $string .= $indent;
  256.     }
  257.  
  258.     # Add the class name
  259.     if ( $self->{display}->{class} ) {
  260.         $string .= ref $Element;
  261.     }
  262.  
  263.     if ( $Element->isa('PPI::Token') ) {
  264.         # Add the content
  265.         if ( $self->{display}->{content} ) {
  266.             my $content = $Element->content;
  267.             $content =~ s/\n/\\n/g;
  268.             $content =~ s/\t/\\t/g;
  269.             $string .= "  \t'$content'";
  270.         }
  271.  
  272.     } elsif ( $Element->isa('PPI::Structure') ) {
  273.         # Add the content
  274.         if ( $self->{display}->{content} ) {
  275.             my $start = $Element->start
  276.                 ? $Element->start->content
  277.                 : '???';
  278.             my $finish = $Element->finish
  279.                 ? $Element->finish->content
  280.                 : '???';
  281.             $string .= "  \t$start ... $finish";
  282.         }
  283.     }
  284.     
  285.     $string;
  286. }
  287.  
  288. 1;
  289.  
  290. =pod
  291.  
  292. =head1 SUPPORT
  293.  
  294. See the L<support section|PPI/SUPPORT> in the main module.
  295.  
  296. =head1 AUTHOR
  297.  
  298. Adam Kennedy E<lt>adamk@cpan.orgE<gt>
  299.  
  300. =head1 COPYRIGHT
  301.  
  302. Copyright 2001 - 2010 Adam Kennedy.
  303.  
  304. This program is free software; you can redistribute
  305. it and/or modify it under the same terms as Perl itself.
  306.  
  307. The full text of the license can be found in the
  308. LICENSE file included with this module.
  309.  
  310. =cut
  311.